

#include "xapp_config.h"

#include "pbm.h"
#include "app_util.h"

#include "xapp_ble.h"

#if USER_CHECK_ENABLED( PEDOMETER )
#include "xapp_pedometer.h"
#endif 

#if USER_CHECK_ENABLED( TOUCHPANEL )
#include "xapp_touchpanel.h"
#endif 

#if USER_CHECK_ENABLED( ECG )
#include "xapp_ecg.h"
#endif 

#include "xFLASH.h"

#if 1 // Memory
pbd_err_code_t pi_mem_write_flash_data( uint8_t *pdata, uint16_t size)
{
    uint32_t address = uint32_decode(pdata);
    uint8_t bytes_to_write = pdata[4]; 

    memcpy( (uint32_t*)address, pdata + 5, bytes_to_write);

    return PBD_SUCCESS; 
}
pbd_err_code_t pi_mem_read_flash_data(uint8_t *pdata, uint16_t size, uint8_t *p_read_data, uint16_t * p_byte_of_read)
{
    uint32_t address = uint32_decode(pdata);
    uint8_t bytes_to_read = pdata[4];

    if(*p_byte_of_read < 4)
        return PBD_ERR_RESOURCE_INSUFFICIENT;

    if( *p_byte_of_read < (bytes_to_read + 4)){
        bytes_to_read = *p_byte_of_read - 4;
    }else{
        *p_byte_of_read = bytes_to_read + 4; 
    }

    uint32_encode( address, p_read_data);
    memcpy( p_read_data + 4, (uint8_t*)address, bytes_to_read);  

    // set latency disable 3seconds( call repeat will reset timer)
    xapp_ble_set_latency_disable( 3 ); // 
    
    return PBD_SUCCESS; 
}



pbd_err_code_t pi_mem_ext_flash_read_device_id(uint8_t *pdata, uint16_t size, uint8_t *res, uint16_t *res_max_len)
{
    return PBD_SUCCESS;
}
pbd_err_code_t pi_mem_ext_flash_read_jedec_id(uint8_t *pdata, uint16_t size, uint8_t *res, uint16_t *res_max_len)
{
    return PBD_SUCCESS;
}

pbd_err_code_t pi_mem_ext_flash_program_data(uint8_t *pdata, uint16_t size)
{
    uint32_t address = uint32_decode(pdata); // address
    uint8_t len = pdata[4];
    if( (len + 5 ) != size ){
        return PBD_ERR_INVALID_LENGTH;
    }

    return PBD_SUCCESS;
}
pbd_err_code_t pi_mem_ext_flash_read_data(uint8_t *pdata, uint16_t size, uint8_t *p_read_data, uint16_t * p_byte_of_read)
{
    uint32_t address = uint32_decode(pdata);
    uint8_t bytes_to_read = pdata[4];

    
    if( *p_byte_of_read < (bytes_to_read + 4)){
        bytes_to_read = *p_byte_of_read - 4;
    }else{
        *p_byte_of_read = bytes_to_read + 4; 
    }

    uint32_encode(address, p_read_data + 4); 
    // suggest use flash read to load data as XIP will use buffer data 
    // memcpy( p_read_data + 4, (uint8_t*)address, bytes_to_read );
    xFLASH_read_data( address, p_read_data + 4, bytes_to_read );
    
    //data[0] = PBD_COMMAND_UPLOAD;
    p_read_data[0] = (uint8_t)( address >> 0 );
    p_read_data[1] = (uint8_t)( address >> 8 );
    p_read_data[2] = (uint8_t)( address >> 16 ); 
    p_read_data[3] = (uint8_t)( address >> 24 );
    
    xapp_ble_set_latency_disable( 3 ); // 
    
    return PBD_SUCCESS; 
}
pbd_err_code_t pi_mem_write_ext_flash_reg(uint8_t *pdata, uint16_t size)
{
    return PBD_SUCCESS; 
}
pbd_err_code_t pi_mem_read_ext_flash_reg(uint8_t *pdata, uint16_t size)
{
    return PBD_SUCCESS; 
}

pbd_err_code_t pi_mem_comm_read_data(uint8_t *pdata, uint16_t size)
{
    return PBD_SUCCESS; 
}
pbd_err_code_t pi_mem_comm_write_data(uint8_t *pdata, uint16_t size)
{
    return PBD_SUCCESS;
}


pbd_err_code_t pi_mem_accel_read_reg(uint8_t *pdata, uint8_t size, uint8_t * reglistval, uint16_t * reglistlen)
{
    return PBD_ERR_SUB_FUNCTION_NOT_SUPPORTED; 

    // uint8_t addlen = pdata[0];
    // uint8_t readlen = pdata[1];
    // uint8_t reg = pdata[2]; 

    // if( readlen < *reglistlen ){
    //     *reglistlen = readlen;
    // }else{
    //     readlen = *reglistlen;
    // }
    // reglistval[0] = addlen;
    // reglistval[1] = reg;

//    gsensor_open_bus();
//    if(readlen == 1){
//        gsensor_read_reg( reg, reglistval + addlen + 1 ); 
//    }else{
//        gsensor_read_multi_reg( reg, reglistval + addlen + 1, readlen);
//    }
//    gsensor_close_bus();

    // return PBD_SUCCESS;
}
pbd_err_code_t pi_mem_accel_write_reg(uint8_t *pdata, uint8_t size)
{
    return PBD_ERR_SUB_FUNCTION_NOT_SUPPORTED;
}
pbd_err_code_t pi_mem_accel_read_data(void)
{
    return PBD_ERR_SUB_FUNCTION_NOT_SUPPORTED;
}
pbd_err_code_t pi_mem_accel_write_data(uint8_t *pdata, uint8_t size)
{
    // accel no not allow to write data for current 
    return PBD_ERR_SUB_FUNCTION_NOT_SUPPORTED;
}
pbd_err_code_t pi_mem_accel_set_fifo_notify(uint8_t *pdata, uint8_t size)
{
    if(size != 1)
    {
        return PBD_ERR_INVALID_LENGTH;
    }

    #if USER_CHECK_ENABLED( PEDOMETER )
    xapp_pedo_param_t para;
    para.type = XAPP_PEDO_PARAM_SET_RAW_NOTIFY;
    para.enable = pdata[0] > 0;
    xapp_pedometer_set_param( &para );
    #endif 

    return PBD_SUCCESS;
}



void pi_mem_accel_fifo_notify(uint8_t *pdata, uint8_t size, pb_tx_array_handle_t cb)
{
    uint8_t txbuff[99];
    if( size > (99-3)){
        size = (99 - 3);
    }
    txbuff[0] = PBD_COMMAND_MEMORY;
    txbuff[1] = size + 1;
    txbuff[2] = PBD_MEMORY_KEY_ACCEL_FIFO_DATA;
    memcpy( txbuff + 3, pdata, size);

    if(cb != NULL){
        pb_assemble_tx_data( txbuff, size + 3, 0, cb ); 
    }

    // pbm_memory_tx_accel_fifo_data( pdata, size, cb ); 
}

pbd_err_code_t pi_mem_comm_read_reg(uint8_t *pdata, uint16_t size, uint8_t * regval, uint8_t *regvallen)
{
    return PBD_SUCCESS;
}
pbd_err_code_t pi_mem_comm_write_reg(uint8_t *pdata, uint16_t size)
{
    return PBD_SUCCESS; 
}

//static bool m_tp_notify_enable = false; 
//static uint32_t m_tp_timestamp = 0; 
//extern bool m_touch_raw_data_is_notify_enabled;
pbd_err_code_t pi_mem_tp_data_write_notify(uint8_t* pdata, uint8_t size)
{
    if( size != 1 )
    {
        return PBD_ERR_INVALID_LENGTH;
    }
#if USER_CHECK_ENABLED( TOUCHPANEL )
    xapp_touchpanel_set_notify( pdata[0] == 1 );
    return PBD_SUCCESS;
#else 
    return PBD_ERR_SUB_FUNCTION_NOT_SUPPORTED;
#endif 
}

void pi_mem_tp_data_notify(uint8_t* pdata, uint8_t size)
{
    pbm_memory_tx_tp_data(pdata, size, XAPP_BLE_PB_TX_HANDLER );    
}

void pi_mem_hrs_data_notify(uint8_t* pdata, uint8_t size)
{
    pbm_memory_tx_hrs_fifo_data( pdata, size, XAPP_BLE_PB_TX_HANDLER );  
}

pb_err_code_t pi_mem_i2c_read_data(uint8_t* pdata, uint8_t size, uint8_t* regval, uint16_t* maxlen)
{
    // 0 & 1 specify address IO pin 
//    uint8_t slave_address = pdata[2];
//    
//    uint8_t reg = pdata[4];
//    uint8_t len = pdata[3];

//    if( i2c_check_is_locked() )
//    {
//        return PBD_ERR_BUSY;
//    }

//    i2c_common_read( slave_address, reg, regval, len );
    
//    *maxlen = len; 

    return PBD_SUCCESS;
}

pb_err_code_t pi_mem_i2c_write_data( uint8_t* pdata, uint8_t size)
{    
//    uint8_t slave_address = pdata[2];
    
//    uint8_t reg = pdata[4];
//    uint8_t len = pdata[3];
    
//    if( i2c_check_is_locked() ) 
//    {
//        return PBD_ERR_BUSY;
//    }
//    
//    i2c_common_write( slave_address, pdata + 4, len );
    
    
    return PBD_SUCCESS;    
}

#endif // !Memory 


#if 1 // active 

void pbm_memory_tx_accel_fifo_data(uint8_t *data, uint16_t len, pb_tx_array_handle_t cb)
{
    uint8_t txbuff[99];
    if( len > (99-3)){
        len = (99 - 3);
    }
    txbuff[0] = PBD_COMMAND_MEMORY;
    txbuff[1] = len + 1;
    txbuff[2] = PBD_MEMORY_KEY_ACCEL_FIFO_DATA;
    memcpy( txbuff + 3, data, len);

    if(cb != NULL){
        pb_assemble_tx_data( txbuff, len + 3, 0, cb ); 
    }
}

void pbm_memory_tx_hrs_fifo_data(uint8_t* pdata, uint16_t len, pb_tx_array_handle_t cb)
{
    uint8_t txbuff[99];
    if( len > (sizeof(txbuff) - 3))
    {
        len = sizeof(txbuff) - 3;
    }

    txbuff[0] = PBD_COMMAND_MEMORY;
    txbuff[1] = len + 1;
    txbuff[2] = PBD_MEMORY_KEY_HRS_FIFO_DATA;
    memcpy( txbuff + 3, pdata, len ); 

    if( cb != NULL )
    {
        pb_assemble_tx_data( txbuff, len + 3, 0, cb );
    }
}

void pbm_memory_tx_tp_data(uint8_t* data, uint8_t len, pb_tx_array_handle_t cb)
{
    uint8_t txbuff[99];
    if( len > (99-3)){
        len = (99 - 3);
    }
    txbuff[0] = PBD_COMMAND_MEMORY;
    txbuff[1] = len + 1;
    txbuff[2] = PBD_MEMORY_KEY_TP_DATA;
    memcpy( txbuff + 3, data, len);

    if(cb != NULL){
        pb_assemble_tx_data( txbuff, len + 3, 0, cb ); 
    }
}

pbd_err_code_t pi_mem_ecg_read_reg(uint8_t *pdata, uint8_t size, uint8_t * reglistval, uint16_t * reglistlen)
{
    return PBD_ERR_SUB_FUNCTION_NOT_SUPPORTED; 

    // uint8_t addlen = pdata[0];
    // uint8_t readlen = pdata[1];
    // uint8_t reg = pdata[2]; 

    // if( readlen < *reglistlen ){
    //     *reglistlen = readlen;
    // }else{
    //     readlen = *reglistlen;
    // }
    // reglistval[0] = addlen;
    // reglistval[1] = reg;

//    gsensor_open_bus();
//    if(readlen == 1){
//        gsensor_read_reg( reg, reglistval + addlen + 1 ); 
//    }else{
//        gsensor_read_multi_reg( reg, reglistval + addlen + 1, readlen);
//    }
//    gsensor_close_bus();

    // return PBD_SUCCESS;
}
pbd_err_code_t pi_mem_ecg_write_reg(uint8_t *pdata, uint8_t size)
{
    return PBD_ERR_SUB_FUNCTION_NOT_SUPPORTED;
}
pbd_err_code_t pi_mem_ecg_read_data(void)
{
    return PBD_ERR_SUB_FUNCTION_NOT_SUPPORTED;
}
pbd_err_code_t pi_mem_ecg_write_data(uint8_t *pdata, uint8_t size)
{
    // accel no not allow to write data for current 
    return PBD_ERR_SUB_FUNCTION_NOT_SUPPORTED;
}
pbd_err_code_t pi_mem_ecg_set_task(uint8_t *pdata, uint8_t size)
{
    if(size != 1)
    {
        return PBD_ERR_INVALID_LENGTH;
    }

    #if 0//USER_CHECK_ENABLED( ECG )
    xapp_ecg_set_task( pdata[0] > 0 );
    #endif 

    return PBD_SUCCESS;
}


void pi_mem_ecg_fifo_notify(uint8_t *pdata, uint8_t size, pb_tx_array_handle_t cb)
{
    uint8_t txbuff[99];
    if( size > (99-3)){
        size = (99 - 3);
    }
    txbuff[0] = PBD_COMMAND_MEMORY;
    txbuff[1] = size + 1;
    txbuff[2] = PBD_MEMORY_KEY_ECG_FIFO_DATA;
    memcpy( txbuff + 3, pdata, size);

    if(cb != NULL){
        pb_assemble_tx_data( txbuff, size + 3, 0, cb ); 
    }

    // pbm_memory_tx_ecg_fifo_data( pdata, size, cb ); 
}

#endif 
